home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / exerion.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  16KB  |  554 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw.c
  4.  
  5.   Functions to emulate the video hardware of the machine.
  6.  
  7. ***************************************************************************/
  8.  
  9. #include "driver.h"
  10. #include "vidhrdw/generic.h"
  11.  
  12. #ifndef INCLUDE_DRAW_CORE
  13.  
  14. //#define DEBUG_SPRITES
  15.  
  16. #define BACKGROUND_X_START        32
  17. #define BACKGROUND_X_START_FLIP    72
  18.  
  19. #define VISIBLE_X_MIN            (12*8)
  20. #define VISIBLE_X_MAX            (52*8)
  21. #define VISIBLE_Y_MIN            (2*8)
  22. #define VISIBLE_Y_MAX            (30*8)
  23.  
  24.  
  25. #ifdef DEBUG_SPRITES
  26. #include <stdio.h>
  27. FILE    *sprite_log;
  28. #endif
  29.  
  30. UINT8 exerion_cocktail_flip;
  31.  
  32. static UINT8 char_palette, sprite_palette;
  33. static UINT8 char_bank;
  34.  
  35. static UINT8 *background_latches;
  36. static UINT16 *background_gfx[4];
  37. static UINT8 current_latches[16];
  38. static int last_scanline_update;
  39.  
  40. static UINT8 *background_mixer;
  41.  
  42. static void draw_background_8(struct osd_bitmap *bitmap);
  43. static void draw_background_16(struct osd_bitmap *bitmap);
  44.  
  45.  
  46. /***************************************************************************
  47.  
  48.   Convert the color PROMs into a more useable format.
  49.  
  50.   The palette PROM is connected to the RGB output this way:
  51.  
  52.   bit 7 -- 220 ohm resistor  -- BLUE
  53.         -- 470 ohm resistor  -- BLUE
  54.         -- 220 ohm resistor  -- GREEN
  55.         -- 470 ohm resistor  -- GREEN
  56.         -- 1  kohm resistor  -- GREEN
  57.         -- 220 ohm resistor  -- RED
  58.         -- 470 ohm resistor  -- RED
  59.   bit 0 -- 1  kohm resistor  -- RED
  60.  
  61. ***************************************************************************/
  62.  
  63. void exerion_vh_convert_color_prom(unsigned char *palette, unsigned short *colortable, const unsigned char *color_prom)
  64. {
  65.     int i;
  66.  
  67.     for (i = 0; i < Machine->drv->total_colors; i++)
  68.     {
  69.         int bit0, bit1, bit2;
  70.  
  71.         /* red component */
  72.         bit0 = (*color_prom >> 0) & 0x01;
  73.         bit1 = (*color_prom >> 1) & 0x01;
  74.         bit2 = (*color_prom >> 2) & 0x01;
  75.         *palette++ = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  76.         /* green component */
  77.         bit0 = (*color_prom >> 3) & 0x01;
  78.         bit1 = (*color_prom >> 4) & 0x01;
  79.         bit2 = (*color_prom >> 5) & 0x01;
  80.         *palette++ = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  81.         /* blue component */
  82.         bit0 = 0;
  83.         bit1 = (*color_prom >> 6) & 0x01;
  84.         bit2 = (*color_prom >> 7) & 0x01;
  85.         *palette++ = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  86.  
  87.         color_prom++;
  88.     }
  89.  
  90.     /* color_prom now points to the beginning of the char lookup table */
  91.  
  92.     /* fg chars */
  93.     for (i = 0; i < 256; i++)
  94.         colortable[i + 0x000] = 16 + (color_prom[(i & 0xc0) | ((i & 3) << 4) | ((i >> 2) & 15)] & 15);
  95.     color_prom += 256;
  96.  
  97.     /* color_prom now points to the beginning of the sprite lookup table */
  98.  
  99.     /* sprites */
  100.     for (i = 0; i < 256; i++)
  101.         colortable[i + 0x100] = 16 + (color_prom[(i & 0xc0) | ((i & 3) << 4) | ((i >> 2) & 15)] & 15);
  102.     color_prom += 256;
  103.  
  104.     /* bg chars (this is not the full story... there are four layers mixed */
  105.     /* using another PROM */
  106.     for (i = 0; i < 256; i++)
  107.         colortable[i + 0x200] = *color_prom++ & 15;
  108. }
  109.  
  110.  
  111.  
  112. /*************************************
  113.  *
  114.  *        Video system startup
  115.  *
  116.  *************************************/
  117.  
  118. int exerion_vh_start (void)
  119. {
  120.     UINT16 *dst;
  121.     UINT8 *src;
  122.     int i, x, y;
  123.  
  124. #ifdef DEBUG_SPRITES
  125.     sprite_log = fopen ("sprite.log","w");
  126. #endif
  127.  
  128.     /* get pointers to the mixing and lookup PROMs */
  129.     background_mixer = memory_region(REGION_PROMS) + 0x320;
  130.  
  131.     /* allocate memory to track the background latches */
  132.     background_latches = malloc(Machine->drv->screen_height * 16);
  133.     if (!background_latches)
  134.         return 1;
  135.  
  136.     /* allocate memory for the decoded background graphics */
  137.     background_gfx[0] = malloc(2 * 256 * 256 * 4);
  138.     background_gfx[1] = background_gfx[0] + 256 * 256;
  139.     background_gfx[2] = background_gfx[1] + 256 * 256;
  140.     background_gfx[3] = background_gfx[2] + 256 * 256;
  141.     if (!background_gfx[0])
  142.     {
  143.         free(background_latches);
  144.         background_latches = NULL;
  145.         return 1;
  146.     }
  147.  
  148.     /*---------------------------------
  149.      * Decode the background graphics
  150.      *
  151.      * We decode the 4 background layers separately, but shuffle the bits so that
  152.      * we can OR all four layers together. Each layer has 2 bits per pixel. Each
  153.      * layer is decoded into the following bit patterns:
  154.      *
  155.      *    000a 0000 00AA
  156.      *  00b0 0000 BB00
  157.      *  0c00 00CC 0000
  158.      *  d000 DD00 0000
  159.      *
  160.      * Where AA,BB,CC,DD are the 2bpp data for the pixel,and a,b,c,d are the OR
  161.      * of these two bits together.
  162.      */
  163.     for (i = 0; i < 4; i++)
  164.     {
  165.         src = memory_region(REGION_GFX3) + i * 0x2000;
  166.         dst = background_gfx[i];
  167.  
  168.         for (y = 0; y < 256; y++)
  169.         {
  170.             for (x = 0; x < 128; x += 4)
  171.             {
  172.                 UINT8 data = *src++;
  173.                 UINT16 val;
  174.  
  175.                 val = ((data >> 3) & 2) | ((data >> 0) & 1);
  176.                 if (val) val |= 0x100 >> i;
  177.                 *dst++ = val << (2 * i);
  178.  
  179.                 val = ((data >> 4) & 2) | ((data >> 1) & 1);
  180.                 if (val) val |= 0x100 >> i;
  181.                 *dst++ = val << (2 * i);
  182.  
  183.                 val = ((data >> 5) & 2) | ((data >> 2) & 1);
  184.                 if (val) val |= 0x100 >> i;
  185.                 *dst++ = val << (2 * i);
  186.  
  187.                 val = ((data >> 6) & 2) | ((data >> 3) & 1);
  188.                 if (val) val |= 0x100 >> i;
  189.                 *dst++ = val << (2 * i);
  190.             }
  191.             for (x = 0; x < 128; x++)
  192.                 *dst++ = 0;
  193.         }
  194.     }
  195.  
  196.     return generic_vh_start();
  197. }
  198.  
  199.  
  200. /*************************************
  201.  *
  202.  *        Video system shutdown
  203.  *
  204.  *************************************/
  205.  
  206. void exerion_vh_stop (void)
  207. {
  208. #ifdef DEBUG_SPRITES
  209.     fclose (sprite_log);
  210. #endif
  211.  
  212.     /* free the background graphics data */
  213.     if (background_gfx[0])
  214.         free(background_gfx[0]);
  215.     background_gfx[0] = NULL;
  216.     background_gfx[1] = NULL;
  217.     background_gfx[2] = NULL;
  218.     background_gfx[3] = NULL;
  219.  
  220.     /* free the background latches data */
  221.     if (background_latches)
  222.         free(background_latches);
  223.     background_latches = NULL;
  224.  
  225.     generic_vh_stop();
  226. }
  227.  
  228.  
  229.  
  230. /*************************************
  231.  *
  232.  *        Video register I/O
  233.  *
  234.  *************************************/
  235.  
  236. WRITE_HANDLER( exerion_videoreg_w )
  237. {
  238.     /* bit 0 = flip screen and joystick input multiplexor */
  239.     exerion_cocktail_flip = data & 1;
  240.  
  241.     /* bits 1-2 char lookup table bank */
  242.     char_palette = (data & 0x06) >> 1;
  243.  
  244.     /* bits 3 char bank */
  245.     char_bank = (data & 0x08) >> 3;
  246.  
  247.     /* bits 4-5 unused */
  248.  
  249.     /* bits 6-7 sprite lookup table bank */
  250.     sprite_palette = (data & 0xc0) >> 6;
  251. }
  252.  
  253.  
  254. WRITE_HANDLER( exerion_video_latch_w )
  255. {
  256.     int ybeam = cpu_getscanline();
  257.  
  258.     if (ybeam >= Machine->drv->screen_height)
  259.         ybeam = Machine->drv->screen_height - 1;
  260.  
  261.     /* copy data up to and including the current scanline */
  262.     while (ybeam != last_scanline_update)
  263.     {
  264.         last_scanline_update = (last_scanline_update + 1) % Machine->drv->screen_height;
  265.         memcpy(&background_latches[last_scanline_update * 16], current_latches, 16);
  266.     }
  267.  
  268.     /* modify data on the current scanline */
  269.     if (offset != -1)
  270.         current_latches[offset] = data;
  271. }
  272.  
  273.  
  274. READ_HANDLER( exerion_video_timing_r )
  275. {
  276.     /* bit 1 is VBLANK */
  277.     /* bit 0 is the SNMI signal, which is low for H >= 0x1c0 and /VBLANK */
  278.  
  279.     int xbeam = cpu_gethorzbeampos();
  280.     int ybeam = cpu_getscanline();
  281.     UINT8 result = 0;
  282.  
  283.     if (ybeam >= VISIBLE_Y_MAX)
  284.         result |= 2;
  285.     if (xbeam < 0x1c0 && ybeam < VISIBLE_Y_MAX)
  286.         result |= 1;
  287.  
  288.     return result;
  289. }
  290.  
  291.  
  292. /*************************************
  293.  *
  294.  *        Core refresh routine
  295.  *
  296.  *************************************/
  297.  
  298. void exerion_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  299. {
  300.     int sx, sy, offs, i;
  301.  
  302.     /* finish updating the scanlines */
  303.     exerion_video_latch_w(-1, 0);
  304.  
  305.     /* draw background */
  306.     if (bitmap->depth == 8)
  307.         draw_background_8(bitmap);
  308.     else
  309.         draw_background_16(bitmap);
  310.  
  311. #ifdef DEBUG_SPRITES
  312.     if (sprite_log)
  313.     {
  314.         int i;
  315.  
  316.         for (i = 0; i < spriteram_size; i+= 4)
  317.         {
  318.             if (spriteram[i+2] == 0x02)
  319.             {
  320.                 fprintf (sprite_log, "%02x %02x %02x %02x\n",spriteram[i], spriteram[i+1], spriteram[i+2], spriteram[i+3]);
  321.             }
  322.         }
  323.     }
  324. #endif
  325.  
  326.     /* draw sprites */
  327.     for (i = 0; i < spriteram_size; i += 4)
  328.     {
  329.         int flags = spriteram[i + 0];
  330.         int y = spriteram[i + 1] ^ 255;
  331.         int code = spriteram[i + 2];
  332.         int x = spriteram[i + 3] * 2 + 72;
  333.  
  334.         int xflip = flags & 0x80;
  335.         int yflip = flags & 0x40;
  336.         int doubled = flags & 0x10;
  337.         int wide = flags & 0x08;
  338.         int code2 = code;
  339.  
  340.         int color = ((flags >> 1) & 0x03) | ((code >> 5) & 0x04) | (code & 0x08) | (sprite_palette * 16);
  341.         const struct GfxElement *gfx = doubled ? Machine->gfx[2] : Machine->gfx[1];
  342.  
  343.         if (exerion_cocktail_flip)
  344.         {
  345.             x = 64*8 - gfx->width - x;
  346.             y = 32*8 - gfx->height - y;
  347.             if (wide) y -= gfx->height;
  348.             xflip = !xflip;
  349.             yflip = !yflip;
  350.         }
  351.  
  352.         if (wide)
  353.         {
  354.             if (yflip)
  355.                 code |= 0x10, code2 &= ~0x10;
  356.             else
  357.                 code &= ~0x10, code2 |= 0x10;
  358.  
  359.             drawgfx(bitmap, gfx, code2, color, xflip, yflip, x, y + gfx->height,
  360.                     &Machine->drv->visible_area, TRANSPARENCY_COLOR, 16);
  361.         }
  362.  
  363.         drawgfx(bitmap, gfx, code, color, xflip, yflip, x, y,
  364.                 &Machine->drv->visible_area, TRANSPARENCY_COLOR, 16);
  365.  
  366.         if (doubled) i += 4;
  367.     }
  368.  
  369.     /* draw the visible text layer */
  370.     for (sy = VISIBLE_Y_MIN/8; sy < VISIBLE_Y_MAX/8; sy++)
  371.         for (sx = VISIBLE_X_MIN/8; sx < VISIBLE_X_MAX/8; sx++)
  372.         {
  373.             int x = exerion_cocktail_flip ? (63*8 - 8*sx) : 8*sx;
  374.             int y = exerion_cocktail_flip ? (31*8 - 8*sy) : 8*sy;
  375.  
  376.             offs = sx + sy * 64;
  377.             drawgfx(bitmap, Machine->gfx[0],
  378.                 videoram[offs] + 256 * char_bank,
  379.                 ((videoram[offs] & 0xf0) >> 4) + char_palette * 16,
  380.                 exerion_cocktail_flip, exerion_cocktail_flip, x, y,
  381.                 &Machine->drv->visible_area, TRANSPARENCY_PEN, 0);
  382.         }
  383. }
  384.  
  385.  
  386. /*************************************
  387.  *
  388.  *        Depth-specific refresh
  389.  *
  390.  *************************************/
  391.  
  392. #define ADJUST_FOR_ORIENTATION(orientation, bitmap, dst, x, y, xadv)    \
  393.     if (orientation)                                                    \
  394.     {                                                                    \
  395.         int dy = bitmap->line[1] - bitmap->line[0];                        \
  396.         int tx = x, ty = y, temp;                                        \
  397.         if (orientation & ORIENTATION_SWAP_XY)                            \
  398.         {                                                                \
  399.             temp = tx; tx = ty; ty = temp;                                \
  400.             xadv = dy / (bitmap->depth / 8);                            \
  401.         }                                                                \
  402.         if (orientation & ORIENTATION_FLIP_X)                            \
  403.         {                                                                \
  404.             tx = bitmap->width - 1 - tx;                                \
  405.             if (!(orientation & ORIENTATION_SWAP_XY)) xadv = -xadv;        \
  406.         }                                                                \
  407.         if (orientation & ORIENTATION_FLIP_Y)                            \
  408.         {                                                                \
  409.             ty = bitmap->height - 1 - ty;                                \
  410.             if ((orientation & ORIENTATION_SWAP_XY)) xadv = -xadv;        \
  411.         }                                                                \
  412.         /* can't lookup line because it may be negative! */                \
  413.         dst = (TYPE *)(bitmap->line[0] + dy * ty) + tx;                    \
  414.     }
  415.  
  416. #define INCLUDE_DRAW_CORE
  417.  
  418. #define DRAW_FUNC draw_background_8
  419. #define TYPE UINT8
  420. #include "exerion.c"
  421. #undef TYPE
  422. #undef DRAW_FUNC
  423.  
  424. #define DRAW_FUNC draw_background_16
  425. #define TYPE UINT16
  426. #include "exerion.c"
  427. #undef TYPE
  428. #undef DRAW_FUNC
  429.  
  430.  
  431. #else
  432.  
  433.  
  434. /*************************************
  435.  *
  436.  *        Background rendering
  437.  *
  438.  *************************************/
  439.  
  440. void DRAW_FUNC(struct osd_bitmap *bitmap)
  441. {
  442.     UINT8 *latches = &background_latches[VISIBLE_Y_MIN * 16];
  443.     int orientation = Machine->orientation;
  444.     int x, y;
  445.  
  446.     /* loop over all visible scanlines */
  447.     for (y = VISIBLE_Y_MIN; y < VISIBLE_Y_MAX; y++, latches += 16)
  448.     {
  449.         UINT16 *src0 = &background_gfx[0][latches[1] * 256];
  450.         UINT16 *src1 = &background_gfx[1][latches[3] * 256];
  451.         UINT16 *src2 = &background_gfx[2][latches[5] * 256];
  452.         UINT16 *src3 = &background_gfx[3][latches[7] * 256];
  453.         int xoffs0 = latches[0];
  454.         int xoffs1 = latches[2];
  455.         int xoffs2 = latches[4];
  456.         int xoffs3 = latches[6];
  457.         int start0 = latches[8] & 0x0f;
  458.         int start1 = latches[9] & 0x0f;
  459.         int start2 = latches[10] & 0x0f;
  460.         int start3 = latches[11] & 0x0f;
  461.         int stop0 = latches[8] >> 4;
  462.         int stop1 = latches[9] >> 4;
  463.         int stop2 = latches[10] >> 4;
  464.         int stop3 = latches[11] >> 4;
  465.         UINT16 *pens = &Machine->remapped_colortable[0x200 + (latches[12] >> 4) * 16];
  466.         UINT8 *mixer = &background_mixer[(latches[12] << 4) & 0xf0];
  467.         TYPE *dst = &((TYPE *)bitmap->line[y])[VISIBLE_X_MIN];
  468.         int xadv = 1;
  469.  
  470.         /* adjust in case we're oddly oriented */
  471.         ADJUST_FOR_ORIENTATION(orientation, bitmap, dst, VISIBLE_X_MIN, y, xadv);
  472.  
  473.         /* the cocktail flip flag controls whether we could up or down in X */
  474.         if (!exerion_cocktail_flip)
  475.         {
  476.             /* skip processing anything that's not visible */
  477.             for (x = BACKGROUND_X_START; x < VISIBLE_X_MIN; x++)
  478.             {
  479.                 if (!(++xoffs0 & 0x1f)) start0++, stop0++;
  480.                 if (!(++xoffs1 & 0x1f)) start1++, stop1++;
  481.                 if (!(++xoffs2 & 0x1f)) start2++, stop2++;
  482.                 if (!(++xoffs3 & 0x1f)) start3++, stop3++;
  483.             }
  484.  
  485.             /* draw the rest of the scanline fully */
  486.             for (x = VISIBLE_X_MIN; x < VISIBLE_X_MAX; x++, dst += xadv)
  487.             {
  488.                 UINT16 combined = 0;
  489.                 UINT8 lookupval, colorindex;
  490.  
  491.                 /* the output enable is controlled by the carries on the start/stop counters */
  492.                 /* they are only active when the start has carried but the stop hasn't */
  493.                 if ((start0 ^ stop0) & 0x10) combined |= src0[xoffs0 & 0xff];
  494.                 if ((start1 ^ stop1) & 0x10) combined |= src1[xoffs1 & 0xff];
  495.                 if ((start2 ^ stop2) & 0x10) combined |= src2[xoffs2 & 0xff];
  496.                 if ((start3 ^ stop3) & 0x10) combined |= src3[xoffs3 & 0xff];
  497.  
  498.                 /* bits 8-11 of the combined value contains the lookup for the mixer PROM */
  499.                 lookupval = mixer[combined >> 8] & 3;
  500.  
  501.                 /* the color index comes from the looked up value combined with the pixel data */
  502.                 colorindex = (lookupval << 2) | ((combined >> (2 * lookupval)) & 3);
  503.                 *dst = pens[colorindex];
  504.  
  505.                 /* the start/stop counters are clocked when the low 5 bits of the X counter overflow */
  506.                 if (!(++xoffs0 & 0x1f)) start0++, stop0++;
  507.                 if (!(++xoffs1 & 0x1f)) start1++, stop1++;
  508.                 if (!(++xoffs2 & 0x1f)) start2++, stop2++;
  509.                 if (!(++xoffs3 & 0x1f)) start3++, stop3++;
  510.             }
  511.         }
  512.         else
  513.         {
  514.             /* skip processing anything that's not visible */
  515.             for (x = BACKGROUND_X_START; x < VISIBLE_X_MIN; x++)
  516.             {
  517.                 if (!(xoffs0-- & 0x1f)) start0++, stop0++;
  518.                 if (!(xoffs1-- & 0x1f)) start1++, stop1++;
  519.                 if (!(xoffs2-- & 0x1f)) start2++, stop2++;
  520.                 if (!(xoffs3-- & 0x1f)) start3++, stop3++;
  521.             }
  522.  
  523.             /* draw the rest of the scanline fully */
  524.             for (x = VISIBLE_X_MIN; x < VISIBLE_X_MAX; x++, dst += xadv)
  525.             {
  526.                 UINT16 combined = 0;
  527.                 UINT8 lookupval, colorindex;
  528.  
  529.                 /* the output enable is controlled by the carries on the start/stop counters */
  530.                 /* they are only active when the start has carried but the stop hasn't */
  531.                 if ((start0 ^ stop0) & 0x10) combined |= src0[xoffs0 & 0xff];
  532.                 if ((start1 ^ stop1) & 0x10) combined |= src1[xoffs1 & 0xff];
  533.                 if ((start2 ^ stop2) & 0x10) combined |= src2[xoffs2 & 0xff];
  534.                 if ((start3 ^ stop3) & 0x10) combined |= src3[xoffs3 & 0xff];
  535.  
  536.                 /* bits 8-11 of the combined value contains the lookup for the mixer PROM */
  537.                 lookupval = mixer[combined >> 8] & 3;
  538.  
  539.                 /* the color index comes from the looked up value combined with the pixel data */
  540.                 colorindex = (lookupval << 2) | ((combined >> (2 * lookupval)) & 3);
  541.                 *dst = pens[colorindex];
  542.  
  543.                 /* the start/stop counters are clocked when the low 5 bits of the X counter overflow */
  544.                 if (!(xoffs0-- & 0x1f)) start0++, stop0++;
  545.                 if (!(xoffs1-- & 0x1f)) start1++, stop1++;
  546.                 if (!(xoffs2-- & 0x1f)) start2++, stop2++;
  547.                 if (!(xoffs3-- & 0x1f)) start3++, stop3++;
  548.             }
  549.         }
  550.     }
  551. }
  552.  
  553. #endif
  554.